package com.zm.study.common;

import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 使用正则表达式验证输入格式
 * Created by zoulei on 2015/12/6.
 */
public class RegexValidateUtil {
	//邮件校验规则
	public static final String REGEX_EMAIL  = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
	//手机号码校验规则
	public static final String REGEX_MOBILE = "^(((13[0-9])|(15([0-3]|[5-9]))|(18[0,5-9]))\\d{8})|(0\\d{2}-\\d{8})|(0\\d{3}-\\d{7})$";
	
	//用户名
	public static final String REGEX_USERNAME = "^\\w{2,20}$";
	
	//密码校验规则
	public static final String REGEX_PWD        = "^\\w{8,}$";
	//包含汉字
	public static final String REGEX_CONTAIN_CH = "[\u4e00-\u9fa5]";
	
	//签名文件类型
	public static final List<String> signFileTypes                       = Arrays.asList("jpg");
	//头像文件类型
	public static final List<String> iconFileTypes                       = Arrays.asList("jpg");
	//简历文件类型
	public static final List<String> resumeFileTypes                     = Arrays.asList("jpg","pdf","doc","docx","zip","rar");
	//正整数类型
	public static final String       REGEX_ZHENGZHENGSHU                 = "^[0-9]*[1-9][0-9]*$";
	//非负整数类型
	public static final String       REGEX_FEIFUZHENGSHU                 = "^[0-9]{1,}$";
	//字母加数字
	public static final String       Letters_Plus_Numbers                = "^[0-9a-zA-Z]*$";
	//字母加数字加下滑线
	public static final String       LettersPlusNumbersPlus_lipperyLines = "^[A-Za-z0-9_]*$";
	//符合电话规范，支持数字+“-”+“（）”+“：”+“+”
	public static final String       Phone                               = "^[0-9+\\-\\++()+:]*$";
	
	//只能是字母
	public static final String Letters_Plus = "^[a-zA-Z]*$";
	
	//只能字母加点
	public static final String Letters_Plus_dian = "^[a-zA-Z.]*$";
	
	//验证网址Url
	public static final String UrlValidation        ="http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";
	//服务器规范
	public static final String Server_Specification ="([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";
	
	//数字
	public static final String Numbers ="^[0-9]*?\\.{0,1}[0-9]{0,2}$";
	
	//只能字母数字加点
	public static final String Letters_PlusNumber_dian = "^[a-z0-9A-Z.]*$";
	//强制密码
	public static final String Strong_Password         ="^(?=.*\\d+.*)(?=.*[A-Za-z]+.*)(?=.*_.*)[\\dA-Za-z_]{13,}$";
	//不强制密码
	public static final String Weak_Password           ="^[A-Za-z0-9_]{2,}$";
			
	final static Map<Integer, String> zoneNum = new HashMap<Integer, String>();
    static {
        zoneNum.put(11, "北京");
        zoneNum.put(12, "天津");
        zoneNum.put(13, "河北");
        zoneNum.put(14, "山西");
        zoneNum.put(15, "内蒙古");
        zoneNum.put(21, "辽宁");
        zoneNum.put(22, "吉林");
        zoneNum.put(23, "黑龙江");
        zoneNum.put(31, "上海");
        zoneNum.put(32, "江苏");
        zoneNum.put(33, "浙江");
        zoneNum.put(34, "安徽");
        zoneNum.put(35, "福建");
        zoneNum.put(36, "江西");
        zoneNum.put(37, "山东");
        zoneNum.put(41, "河南");
        zoneNum.put(42, "湖北");
        zoneNum.put(43, "湖南");
        zoneNum.put(44, "广东");
        zoneNum.put(45, "广西");
        zoneNum.put(46, "海南");
        zoneNum.put(50, "重庆");
        zoneNum.put(51, "四川");
        zoneNum.put(52, "贵州");
        zoneNum.put(53, "云南");
        zoneNum.put(54, "西藏");
        zoneNum.put(61, "陕西");
        zoneNum.put(62, "甘肃");
        zoneNum.put(63, "青海");
        zoneNum.put(64, "新疆");
        zoneNum.put(71, "台湾");
        zoneNum.put(81, "香港");
        zoneNum.put(82, "澳门");
        zoneNum.put(91, "外国");
    }
     
    final static int[] PARITYBIT = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
    final static int[] POWER_LIST = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};

    //只包含纯中文
    public static final String REGEX_CONTAIN_CH_ONLY = "[\u4e00-\u9fa5]+";
     
    /**
     * 身份证验证
     *@param s  号码内容
     *@return 是否有效 null和"" 都是false 
     *
	 * 身份证验证的工具（支持5位或18位省份证）
	 * 身份证号码结构：
	 * 17位数字和1位校验码：6位地址码数字，8位生日数字，3位出生时间顺序号，1位校验码。
	 * 地址码（前6位）：表示对象常住户口所在县（市、镇、区）的行政区划代码，按GB/T2260的规定执行。
	 * 出生日期码，（第七位 至十四位）：表示编码对象出生年、月、日，按GB按GB/T7408的规定执行，年、月、日代码之间不用分隔符。
	 * 顺序码（第十五位至十七位）：表示在同一地址码所标示的区域范围内，对同年、同月、同日出生的人编订的顺序号，
	 * 顺序码的奇数分配给男性，偶数分配给女性。 
	 * 校验码（第十八位数）：
	 * 十七位数字本体码加权求和公式 s = sum(Ai*Wi), i = 0,,16，先对前17位数字的权求和；   
	 *  Ai:表示第i位置上的身份证号码数字值.Wi:表示第i位置上的加权因.Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2；
	 * 计算模 Y = mod(S, 11) 
	 * 通过模得到对应的校验码 Y: 0 1 2 3 4 5 6 7 8 9 10 校验码: 1 0 X 9 8 7 6 5 4 3 2 
	 */
 
    public static boolean isIDCard(String certNo){
        if(certNo == null || (certNo.length() != 15 && certNo.length() != 18))
            return false;
        final char[] cs = certNo.toUpperCase().toCharArray();
        //校验位数
        int power = 0;
        for(int i=0; i<cs.length; i++){
            if(i==cs.length-1 && cs[i] == 'X')
                break;//最后一位可以 是X或x
            if(cs[i]<'0' || cs[i]>'9')
                return false;
            if(i < cs.length -1){
                power += (cs[i] - '0') * POWER_LIST[i];
            }
        }
         
        //校验区位码
        if(!zoneNum.containsKey(Integer.valueOf(certNo.substring(0,2)))){
            return false;
        }
         
        //校验年份
        String year = certNo.length() == 15 ? getIdcardCalendar() + certNo.substring(6,8) :certNo.substring(6, 10);
         
        final int iyear = Integer.parseInt(year);
        if(iyear < 1900 || iyear > Calendar.getInstance().get(Calendar.YEAR))
            return false;//1900年的PASS，超过今年的PASS
         
        //校验月份
        String month = certNo.length() == 15 ? certNo.substring(8, 10) : certNo.substring(10,12);
        final int imonth = Integer.parseInt(month);
        if(imonth <1 || imonth >12){
            return false;
        }
         
        //校验天数      
        String day = certNo.length() ==15 ? certNo.substring(10, 12) : certNo.substring(12, 14);
        final int iday = Integer.parseInt(day);
        if(iday < 1 || iday > 31)
            return false;       
         
        //校验"校验码"
        if(certNo.length() == 15)
            return true;
        return cs[cs.length -1 ] == PARITYBIT[power % 11];
    }
     
    private static int getIdcardCalendar() {        
         GregorianCalendar curDay = new GregorianCalendar();
         int curYear = curDay.get(Calendar.YEAR);
         int year2bit = Integer.parseInt(String.valueOf(curYear).substring(2));
         return  year2bit;
    }


	public static void main(String[] args) {
	 
         System.out.println(checkZhengzhengshu(0));

         System.out.println(checkEmail("gsdf@qq.cim"));

        

//         System.out.println(isIDCard("152627198906084014"));
	}
	
    /**
     * 验证邮箱
     * @param email
     * @return
     */
    public static boolean checkEmail(String email){
        boolean flag = false;
        try{
            Pattern regex = Pattern.compile(REGEX_EMAIL);
            Matcher matcher = regex.matcher(email);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
        return flag;
    }



    /**
     * 验证手机号码
     * @param mobileNumber
     * @return
     */
    public static boolean checkMobileNumber(String mobileNumber){
        boolean flag = false;
        try{
            Pattern regex = Pattern.compile(REGEX_MOBILE);
            Matcher matcher = regex.matcher(mobileNumber);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
        return flag;
    }
    
    /**
     * 检验用户名
     * @param userName
     * @return
     */
    public static boolean checkUserName(String userName){
    	boolean flag = false;
        try{
            Pattern regex = Pattern.compile(REGEX_USERNAME);
            Matcher matcher = regex.matcher(userName);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
        return flag;
    }
    
    /**
     * 检验密码
     * @param pwd
     * @return
     */
    public static boolean checkPassword(String pwd){
    	boolean flag = false;
        try{
            Pattern regex = Pattern.compile(REGEX_PWD);
            Matcher matcher = regex.matcher(pwd);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
        return flag;
    }
    
    /**
     * 是否包含汉字
     * @param path
     * @return
     */
    public static boolean checkConstainCH(String path){
    	 Pattern regex = Pattern.compile(REGEX_CONTAIN_CH);
         Matcher matcher = regex.matcher(path);
         while(matcher.find()){
        	 return true;
         }
         return false;
    }
    
    /**
     * 校验签名文件类型
     * @param fileName
     * @return
     */
    public static boolean isSignFileType(String fileName){
    	String type = fileName.substring(fileName.lastIndexOf('.')+1);
//    	signFileTypes.contains(o)
    	for(String t: signFileTypes){
    		if(t.equalsIgnoreCase(type)){return true;}
    	}
    	return false;
    }
    
    /**
     * 校验头像文件类型
     * @param fileName
     * @return
     */
    public static boolean isIconFileType(String fileName){
    	String type = fileName.substring(fileName.lastIndexOf('.')+1);
//    	signFileTypes.contains(o)
    	for(String t: iconFileTypes){
    		if(t.equalsIgnoreCase(type)){return true;}
    	}
    	return false;
    }
    
    /**
     * 校验简历文件类型
     * @param fileName
     * @return
     */
    public static boolean isResumeFileType(String fileName){
    	String type = fileName.substring(fileName.lastIndexOf('.')+1);
//    	signFileTypes.contains(o)
    	for(String t: resumeFileTypes){
    		if(t.equalsIgnoreCase(type)){return true;}
    	}
    	return false;
    }
    
    /**
     * 检验正整数不包括0
     * @param shu
     * @return
     */
    public static boolean checkZhengzhengshustr(String shu){
    	boolean flag = false;
        try{
            Pattern regex = Pattern.compile(REGEX_ZHENGZHENGSHU);
            Matcher matcher = regex.matcher(shu);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
        return flag;
    }	
    
    public static boolean checkZhengzhengshu(Integer shu){
    	boolean flag = false;
        try{
            Pattern regex = Pattern.compile(REGEX_ZHENGZHENGSHU);
            Matcher matcher = regex.matcher(shu.toString());
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
        return flag;
    }	
    
    /**
     * 检验非负整数包括0
     * @param shu
     * @return
     */
    public static boolean checkFeifuzhengshustr(String shu){
    	boolean flag = false;
        try{
            Pattern regex = Pattern.compile(REGEX_FEIFUZHENGSHU);
            Matcher matcher = regex.matcher(shu);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
        return flag;
    }	
    /**
     * 检验非负整数包括0
     * @param shu
     * @return
     */
    public static boolean checkFeifuzhengshu(Integer shu){
    	boolean flag = false;
        try{
            Pattern regex = Pattern.compile(REGEX_FEIFUZHENGSHU);
            Matcher matcher = regex.matcher(shu.toString());
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
        return flag;
    }
    
    /**
     * 字母加数字
     * @param shu
     * @return
     */
    public static boolean LettersPlusNumbers(String shu){
    	boolean flag = false;
    	try{
            Pattern regex = Pattern.compile(Letters_Plus_Numbers);
            Matcher matcher = regex.matcher(shu);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
    	
		return flag;
    	
    }
    
    /**
     * 字母加数字加下划线
     * @param shu
     * @return
     */
    public static boolean LettersPlusNumbersPluslipperyLines(String shu){
    	boolean flag = false;
    	try{
            Pattern regex = Pattern.compile(LettersPlusNumbersPlus_lipperyLines);
            Matcher matcher = regex.matcher(shu);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
    	
		return flag;
    }
    
    
    /**
     * 符合电话规范，支持数字+“-”+“（）”+“：”+“+”
     * @param shu
     * @return
     */
    public static boolean IsPhone(String shu){
    	boolean flag = false;
    	try{
            Pattern regex = Pattern.compile(Phone);
            Matcher matcher = regex.matcher(shu);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
    	
		return flag;
    }
    
    
    /**
     * 只能字母
     * @param shu
     * @return
     */
    public static boolean LettersPlus(String shu){
    	boolean flag = false;
    	try{
            Pattern regex = Pattern.compile(Letters_Plus);
            Matcher matcher = regex.matcher(shu);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
    	
		return flag;
    	
    }
    
    /**
     * 只能字母加点
     * @param shu
     * @return
     */
    public static boolean Letters_Plus_dianstr(String str){
    	boolean flag = false;
    	try{
            Pattern regex = Pattern.compile(Letters_Plus_dian);
            Matcher matcher = regex.matcher(str);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
    	
		return flag;
    	
    }
    
    public static boolean Letters_Plus_dianshu(Integer shu){
    	boolean flag = false;
    	try{
            Pattern regex = Pattern.compile(Letters_Plus_dian);
            Matcher matcher = regex.matcher(shu.toString());
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
    	
		return flag;
    	
    }
    
    /**
     * 服务器规范
     * 
     */
    public static boolean Server_Specification(String str){
    	boolean flag = false;
    	try{
            Pattern regex = Pattern.compile(Server_Specification);
            Matcher matcher = regex.matcher(str);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
    	
		return flag;
    	
    }
    
    /**
     * 数字
     * @param str
     * @return
     */
    public static boolean Numbersstr(String str){
    	boolean flag = false;
        try{
            Pattern regex = Pattern.compile(Numbers);
            Matcher matcher = regex.matcher(str);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
        return flag;
    }	
    /**
     * 数字
     * @param shu
     * @return
     */
    public static boolean Numbersshu(Integer shu){
    	boolean flag = false;
        try{
            Pattern regex = Pattern.compile(Numbers);
            Matcher matcher = regex.matcher(shu.toString());
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
        return flag;
    }
    
    /**
     * 只能字母加点
     * @param shu
     * @return
     */
    public static boolean Letters_PlusNumber_dianstr(String str){
    	boolean flag = false;
    	try{
            Pattern regex = Pattern.compile(Letters_PlusNumber_dian);
            Matcher matcher = regex.matcher(str);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
    	
		return flag;
    	
    }
    
    public static boolean Letters_PlusNumber_dianshu(Integer shu){
    	boolean flag = false;
    	try{
            Pattern regex = Pattern.compile(Letters_PlusNumber_dian);
            Matcher matcher = regex.matcher(shu.toString());
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
    	
		return flag;
    	
    }
    /**
     * 强密码
     * @param str
     * @return
     */
    public static boolean Strong_Passwordstr(String str){
    	boolean flag = false;
    	try{
            Pattern regex = Pattern.compile(Strong_Password);
            Matcher matcher = regex.matcher(str);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
    	
		return flag;
    	
    }
    
    /**
     * 弱密码
     * @param str
     * @return
     */
    public static boolean Weak_Passwordstr(String str){
    	boolean flag = false;
    	try{
            Pattern regex = Pattern.compile(Weak_Password);
            Matcher matcher = regex.matcher(str);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
    	
		return flag;
    	
    }

    /**
     * 只包含纯汉字
     * @param str
     * @return
     */
    public static boolean checkConstainCHOnly(String str){
        boolean flag = false;
        try{
            Pattern regex = Pattern.compile(REGEX_CONTAIN_CH_ONLY);
            Matcher matcher = regex.matcher(str);
            flag = matcher.matches();
        }catch(Exception e){
            flag = false;
        }
        return flag;
    }


}
